from typing import List

from sqlalchemy import exc, and_, func
from sqlalchemy.orm import Session, joinedload, with_loader_criteria

from model.ParamModel import MenuModel, PortMenuModel
from util.ErrorCode import ErrorCode
from util.LogHelper import Log


def get_menus(port_id: int, db: Session):
    try:
        result = db.query(MenuModel).options(joinedload(MenuModel.port_menu), with_loader_criteria(PortMenuModel,
                                                                                                   PortMenuModel.port_id == port_id)).all()
        return {'code': ErrorCode.SUCCESS.value, 'message': 'success', 'data': result}
    except exc.SQLAlchemyError as e:
        Log.getlogger().error(f'get_menus failed! port_id: {port_id} message: {e}')
        return {'code': ErrorCode.DATABASE_ERROR.value, 'message': 'database error'}


def has_permission(port_id: int, function_path: str, db: Session):
    try:
        portMenuModel = db.query(PortMenuModel).filter(
            and_(PortMenuModel.port_id == port_id, func.instr(function_path, PortMenuModel.function_path) > 0,
                 PortMenuModel.flag == 1)).one_or_none()
        if portMenuModel is None:
            return False
        else:
            return True
    except exc.SQLAlchemyError as e:
        Log.getlogger().error(f'has_permission failed! port_id: {port_id} function_path: {function_path} message: {e}')
        return False


def batch_port_menu(port_id: int, menuInfos: List, db: Session):
    try:
        for menuInfo in menuInfos:
            portMenuModel = db.query(PortMenuModel).filter(
                and_(PortMenuModel.port_id == port_id, PortMenuModel.menu_id == menuInfo.menu_id,
                     PortMenuModel.function_path == menuInfo.function_path)).one_or_none()
            if portMenuModel is None:
                portMenuModel = PortMenuModel(port_id=port_id, menu_id=menuInfo.menu_id,
                                              function_path=menuInfo.function_path, flag=menuInfo.flag)
                db.add(portMenuModel)
            else:
                portMenuModel.flag = menuInfo.flag
        db.commit()
        return {'code': ErrorCode.SUCCESS.value, 'message': 'success'}
    except exc.SQLAlchemyError as e:
        db.rollback()
        Log.getlogger().error(f'batch_port_menu failed! port_id:{port_id} menuInfos: {menuInfos} message: {e}')
        return {'code': ErrorCode.DATABASE_ERROR.value, 'message': 'database error'}


